package com.jxtpro.generator;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import com.alibaba.druid.pool.DruidDataSource;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.dialect.Dialect;
import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
import com.jfinal.plugin.activerecord.generator.ColumnMeta;
import com.jfinal.plugin.activerecord.generator.MetaBuilder;
import com.jfinal.plugin.activerecord.generator.TableMeta;
import com.jfinal.plugin.activerecord.generator.TypeMapping;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.template.Engine;
import com.jfinal.template.Template;
import com.jfinal.template.source.ClassPathSourceFactory;
import com.xiaoleilu.hutool.io.FileUtil;

public class MVCGenerator extends AbstractGenerator{
	

	@Override
	DataSource getDataSource(String url, String u, String p) throws Exception {
		DruidPlugin dp = new DruidPlugin(url,u, p);
		dp.start();
		DruidDataSource ds = (DruidDataSource)dp.getDataSource();
		Properties properties = new Properties();
		properties.setProperty("remarks", "true");
		properties.setProperty("useInformationSchema", "true");
		ds.setConnectProperties(properties);
		
		return dp == null ? null: ds;
	}

	@Override
	Engine setEngine() {
		return Engine.use()
				.addSharedMethod(new StrKit())
				.setEncoding("utf-8")
				.setSourceFactory(new ClassPathSourceFactory());
	}

	@Override
	MetaBuilder getMetaBuilder(DataSource dataSource) throws Exception {
		MetaBuilder metaBuilder = new MetaBuilder(dataSource);
		metaBuilder.setDialect(getDialect());
		metaBuilder.setTypeMapping(getTypeMapping());
		metaBuilder.addExcludedTable(getExcludedTables());
		metaBuilder.setRemovedTableNamePrefixes(getRemovedTableNamePrefixes());
		return metaBuilder;
	}

	@Override
	void setMetaBuilderDialect(MetaBuilder metaBuilder, Dialect dialect) {
		if(metaBuilder != null){
			metaBuilder.setDialect(getDialect());
		}
	}

	@Override
	Dialect getDialect() {
		return new MysqlDialect();
	}

	@Override
	void setMetaBuilderExcludedTable(MetaBuilder metaBuilder, String[] excludedTables) {
		if(metaBuilder != null){
			metaBuilder.addExcludedTable(excludedTables);
		}
	}

	@Override
	String[] getExcludedTables() {
		return null;
	}

	@Override
	void setMetaBuilderTypeMapping(MetaBuilder metaBuilder, TypeMapping typeMapping) {
		if(metaBuilder != null){
			metaBuilder.setTypeMapping(getTypeMapping());
		}
	}

	@Override
	TypeMapping getTypeMapping() {
		return new TypeMapping();
	}

	@Override
	void setMetaBuilderRemovedTableNamePrefixes(MetaBuilder metaBuilder, String[] removedTableNamePrefixes) {
		if(metaBuilder != null){
			metaBuilder.setRemovedTableNamePrefixes(removedTableNamePrefixes);
		}
	}

	@Override
	String[] getRemovedTableNamePrefixes() {
		String[] removes = {"t_","sys_"};
		return removes;
	}

	@Override
	List<TableMeta> getTableMetas(MetaBuilder metaBuilder) throws Exception {
		if(metaBuilder != null){
			return metaBuilder.build();
		}
		return null;
	}

	@Override
	Map<String, Object> setMetas(Map<String, Object> content) {
		if(content == null || content.size() <= 0){
			content = new HashMap<String,Object>();
		}
		content.put("rootRouteUpName", StrKit.firstCharToUpperCase(String.valueOf(content.get("rootRoute"))));
		content.put("rootRouteLowName", content.get("rootRoute"));
		content.put("configName", StrKit.firstCharToUpperCase(String.valueOf(content.get("projectName"))) + "Config");
		//项目名
		content.put("projectName", content.get("projectName"));
		content.put("projectFilterName", StrKit.firstCharToUpperCase(String.valueOf(content.get("projectName")).replace("-", "")));
		content.put("projectFilterLowName", StrKit.firstCharToLowerCase(String.valueOf(content.get("projectName")).replace("-", "")));
		return content;
	}

	@Override
	List<ColumnMeta> getColumnMetas(TableMeta tableMeta) throws Exception {
		if(tableMeta != null){
			return tableMeta.columnMetas;
		}
		return null;
	}
	@Override
	void doTask(Engine engine, List<TableMeta> tableMetas, Map<String, Object> content, List<List<String>> tempList)
			throws Exception {
		 List<Map<String,Object>> metas = new ArrayList<Map<String,Object>>();
		 String[] templates = {"controller.html", "service.html"
				,"serviceImpl.html","dao.html","basedao.html","vo.html"};
		 String[] paths = {"controller","service"
				,"service/impl","model","model/base","vo"};
		 String[] fileNames = {"Controller.java"
				,"Service.java","ServiceImpl.java",".java",".java","VO.java"};
		 
		 for (int i = 0; i < templates.length; i++) {
				templates[i]= "generator/java/"+templates[i];
		 }
		
		for (TableMeta table : tableMetas) {
			String claLowName = StrKit.firstCharToLowerCase(StrKit.toCamelCase(table.modelName));
			String claUpName = StrKit.firstCharToUpperCase(StrKit.toCamelCase(table.modelName));;
			Map<String,Object> meta = new HashMap<String,Object>(); 
			meta.put("cols", table.columnMetas);
			meta.put("claUpName", claUpName);
			meta.put("claLowName", claLowName);
			meta.put("tableName", table.name);
			content.put("remarks", table.remarks);
			content.put("meta", meta);
			content.put("table", table);
			content.put("cols", table.columnMetas);
			content.put("claUpName", claUpName);
			content.put("claLowName", claLowName);
			content.put("tableName", table.name);
			for (int i = 0; i < templates.length; i++) {
				Template template = engine.getTemplate(templates[i]);
				// 模板为basedao时做特殊处理,可以去掉
				String fileName = null;
				if ("generator/java/basedao.html".equals(templates[i])) {
					fileName = toOutJavaPath(paths[i],content) + "Base" + table.modelName + fileNames[i];
				}
				else {
					fileName = toOutJavaPath(paths[i],content) + table.modelName + fileNames[i];
				}
				writeFiles(template, content, fileName,false);
			}
			metas.add(meta);
			//生成 每张表的sql 文件
			writeFiles(engine.getTemplate("generator/sql/table_sql.html"), content, toOutResourcesPath("sql",content) + "/"+claLowName+".sql",true);
			//生成html
			//toOutWEBINF("pages/"+rootRoute+"/"+claLowName);
			writeFiles(engine.getTemplate("generator/view/model/index.html"), content, toOutWEBINF("pages/"+String.valueOf(content.get("rootRoute"))+"/"+claLowName,content)+"/index.html",true);
			writeFiles(engine.getTemplate("generator/view/model/detail.html"), content, toOutWEBINF("pages/"+String.valueOf(content.get("rootRoute"))+"/"+claLowName,content)+"/detail.html",true);
			writeFiles(engine.getTemplate("generator/view/model/_form.html"), content, toOutWEBINF("pages/"+String.valueOf(content.get("rootRoute"))+"/"+claLowName,content)+"/_form.html",true);
		}
		content.put("metas", metas);
		content.put("configName", StrKit.firstCharToUpperCase(String.valueOf(content.get("projectPackage"))) + "Config");
		//项目名
		content.put("projectName", content.get("projectName"));
		content.put("projectFilterName", StrKit.firstCharToUpperCase(String.valueOf(content.get("projectName")).replace("-", "")));
		content.put("projectFilterLowName", StrKit.firstCharToLowerCase(String.valueOf(content.get("projectName")).replace("-", "")));
	
		//生成附加java文件
		genJava(content,engine);
		//生成sql-all文件
		genAllSql(content,engine);
		// mapping 映射
		genMapping(content,engine);
		// 生成路由
		genRoutes(content,engine);
		// 继续拓展 生成 config
		genConfig(content,engine);
		// web.xml
		genWebXml(content,engine);
		// config_dev.properties
		genDevConfig(content,engine);
		// config_pro.properties
		genProConfig(content,engine);
		// pom.xml
		gengPom(content,engine);
		//page /comm layout_admin.html
		writeFiles(engine.getTemplate("generator/view/comm/layout_admin.html"), content, toOutWEBINF("pages/comm",content)+"/layout_admin.html",true);
		// ------------------------------------- copy resources ----------------------------------------
		System.out.println("------------ copy resources --------");
		FileUtil.copy(PathKit.getRootClassPath()+"/generator/view/index", toOutWEBINF("pages/"+String.valueOf(content.get("rootRoute")),content), false);
		FileUtil.copy(PathKit.getRootClassPath()+"/generator/view/assets", toOutWebApp("",content), false);
		System.out.println("------------ ok 刷新项目  --------");
	}
	/**
	 * 生成mapping
	 * @param content
	 */
	private void genMapping(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/java/_MappingKit.html"), content, toOutJavaPath("model",content) + "_MappingKit.java",true);
		} catch (Exception e) {
			System.out.println("--- _MappingKit生成失败 ---");
			e.printStackTrace();
		}
	}
	/**
	 * 生成config_pro.properties配置文件
	 */
	private void genProConfig(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/config_dev.html"), content, toOutResourcesPath("",content) + "config_pro.properties",true);
		} catch (Exception e) {
			System.out.println("--- config_dev.propertis生成失败 ---");
			e.printStackTrace();
		}		
	}

	/**
	 * 生成config_dev.properties配置文件
	 */
	private void genDevConfig(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/config_pro.html"), content, toOutResourcesPath("",content) + "config_dev.properties",true);
		} catch (Exception e) {
			System.out.println("--- config_pro.propertis生成失败 ---");
			e.printStackTrace();
		}
	}
	/**
	 * 生成web.xml
	 */
	private void genWebXml(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/web.html"), content, toOutWEBINF("",content) + "web.xml",true);
		} catch (Exception e) {
			System.out.println("--- web.xml生成失败 ---");
			e.printStackTrace();
		}		
	}

	/**
	 * 生成pom文件
	 * @param content
	 */
	private void gengPom(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/pom.html"), content, toOutSrcPath("",content) + "pom.xml",true);
		} catch (Exception e) {
			System.out.println("--- pom.xml生成失败 ---");
			e.printStackTrace();
		}
	}

	/**
	 * 生成config
	 */
	private void genConfig(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/java/config.html"), content,
					toOutJavaPath("",content) + content.get("projectFilterName") + "Config.java",true);
		} catch (Exception e) {
			System.out.println("--- config.java生成失败 ---");
			e.printStackTrace();
		}

	}

	/**
	 *  路由 映射
	 */
	private void genRoutes(Map<String, Object> content,Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/java/AdminRoutes.html"), content,
					toOutJavaPath("",content) + StrKit.firstCharToUpperCase(String.valueOf(content.get("rootRoute"))) + "Routes.java",true);
		} catch (Exception e) {
			System.out.println("--- 路由生成失败 ---");
			e.printStackTrace();
		}
	}
	/**
	 * 生成all_sqls.sql 文件
	 * @param content
	 * @param engine
	 */
	private void genAllSql(Map<String, Object> content, Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/sql/all_sqls.html"), content, toOutResourcesPath("sql",content) + "/all_sqls.sql",true);
		} catch (Exception e) {
			System.out.println("--- sql文件生成失败 ---");
			e.printStackTrace();
		}	
	}
	/**
	 * 生成附加java文件
	 * @param content
	 * @param engine
	 */
	private void genJava(Map<String, Object> content, Engine engine) {
		try {
			writeFiles(engine.getTemplate("generator/java/ParamsUtils.html"), content, toOutJavaPath("comment/utils",content) + "/ParamsUtils.java",true);
			writeFiles(engine.getTemplate("generator/java/ResultData.html"), content, toOutJavaPath("comment/utils",content) + "/ResultData.java",true);
			writeFiles(engine.getTemplate("generator/sql/FieldDirective.html"), content, toOutJavaPath("comment/directive",content) + "/FieldDirective.java",true);
			writeFiles(engine.getTemplate("generator/java/IndexController.html"), content, toOutJavaPath("controller",content) + "/IndexController.java",true);
		} catch (Exception e) {
			System.out.println("--- 附加java文件生成失败 ---");
			e.printStackTrace();
		}
	}


}
